﻿namespace Ross.BSCSystem
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Security.Principal;
    using System.Text;
    using System.Threading;
    using System.Web;
    using System.Web.Http.Controllers;
    using System.Web.Http.Filters;

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public class BasicAuthenticationFilter : AuthorizationFilterAttribute
    {
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            var userIdentity = ParseHeader(actionContext);
            if (userIdentity == null)
            {
                Challenge(actionContext);
                return;
            }

            if (!OnAuthorize(userIdentity.Name, userIdentity.Password, actionContext))
            {
                Challenge(actionContext);
                return;
            }

            //在认证成功后将认证身份设置给当前线程中Principal属性,【身份】+【角色】
            var principal = new GenericPrincipal(userIdentity, null);
            Thread.CurrentPrincipal = principal;

            base.OnAuthorization(actionContext);
        }

        /// <summary>
        /// 对于客户端发送过来的请求我们肯定是需要获得请求报头，然后解析请求报头中的Authorization，若此时其参数为空，我们将返回到客户端，并发起质询.
        /// </summary>
        /// <param name="actionContext"></param>
        /// <returns></returns>
        public virtual BasicAuthenticationIdentity ParseHeader(HttpActionContext actionContext)
        {
            string authParameter = null;

            var authValue = actionContext.Request.Headers.Authorization;
            if (authValue != null && authValue.Scheme == "Basic")
                authParameter = authValue.Parameter;

            if (string.IsNullOrEmpty(authParameter))

                return null;

            authParameter = Encoding.Default.GetString(Convert.FromBase64String(authParameter));

            var authToken = authParameter.Split(':');
            if (authToken.Length < 2)
                return null;

            return new BasicAuthenticationIdentity(authToken[0], authToken[1]);
        }

        /// <summary>
        /// 认证未通过而需要发起认证质询.
        /// </summary>
        /// <param name="actionContext"></param>
        private void Challenge(HttpActionContext actionContext)
        {
            var host = actionContext.Request.RequestUri.DnsSafeHost;
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            actionContext.Response.Headers.Add("WWW-Authenticate", string.Format("Basic realm=\"{0}\"", host));
        }

        /// <summary>
        /// 对用户名和密码进行校验，并将其修饰为虚方法，以免后续要添加其他有关用户数据.
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <param name="actionContext"></param>
        /// <returns></returns>
        public virtual bool OnAuthorize(string username, string password, HttpActionContext actionContext)
        {
            if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
                return false;
            else
                return true;
        }
    }
}